package com.runfast.common.security.spring;

import com.runfast.common.dao.model.RunfastCuser;
import com.runfast.common.service.RunfastCuserService;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.authority.mapping.GrantedAuthoritiesMapper;
import org.springframework.security.core.authority.mapping.NullAuthoritiesMapper;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.util.Assert;

/**
 * @author: lijin
 * @date: 2018年06月02日
 */
public class MobileSmsCodeAuthenticationProvider implements AuthenticationProvider {
    private GrantedAuthoritiesMapper authoritiesMapper = new NullAuthoritiesMapper();

    private RunfastCuserService cuserService;

    public MobileSmsCodeAuthenticationProvider(RunfastCuserService cuserService) {
        this.cuserService = cuserService;
    }

    @Override
    public Authentication authenticate(Authentication authentication) throws AuthenticationException {
        Assert.isInstanceOf(MobileSmsCodeAuthenticationToken.class, authentication, "not instance of MobileSmsCodeAuthenticationToken.class");
        String mobile = authentication.getPrincipal() == null ? "" : authentication.getName();

        String smsCode = authentication.getCredentials() == null ? "" : authentication.getCredentials().toString();
        UserDataDetails<RunfastCuser> userDataDetails = cuserService.checkMobielSmsCode(mobile, smsCode);

        return createSuccessAuthentication(userDataDetails, authentication, userDataDetails);
    }

    @Override
    public boolean supports(Class<?> authentication) {
        return MobileSmsCodeAuthenticationToken.class.isAssignableFrom(authentication);
    }

    protected Authentication createSuccessAuthentication(Object principal,
                                                         Authentication authentication, UserDetails user) {
        // Ensure we return the original credentials the user supplied,
        // so subsequent attempts are successful even with encoded passwords.
        // Also ensure we return the original getDetails(), so that future
        // authentication events after cache expiry contain the details
        MobileSmsCodeAuthenticationToken result = new MobileSmsCodeAuthenticationToken(
                principal, authentication.getCredentials(),
                authoritiesMapper.mapAuthorities(user.getAuthorities()));
        result.setDetails(authentication.getDetails());

        return result;
    }
}
